from PyQt5.QtWidgets import QHeaderView, QTreeWidget, QTreeView, QAction, QInputDialog, QMenu, QTreeWidgetItemIterator, \
    QTableWidget, QTableWidgetItem
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QIcon, QBrush, QColor, QFont
from rss_reader.logger import logger
from rss_reader.database.models import Article, Feed
from rss_reader.models.models import FeedTreeModel
from typing import Dict
from PyQt5.QtWidgets import QTreeWidgetItem
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QIcon
from rss_reader.database_manager import DataBaseManager

class FeedTreeWidget(QTreeWidget):
    """
    Feed Tree Widget
    """
    # feed_selected = pyqtSignal(int, str)  # (feed_id, item_type)

    def __init__(self, parent):
        super().__init__(parent)
        self._unread_counts = {}
        self.session = parent.session
        self.setup_ui()

    def setup_ui(self):
        self.setHeaderHidden(True)
        self.setColumnCount(1)
        self.setSelectionBehavior(QTreeWidget.SelectRows)
        self.setAnimated(True)

        # 连接信号
        # self.itemClicked.connect(self._on_item_clicked)

    def load_feeds(self):
        """加载订阅源数据"""
        self.clear()
        feeds = self.session.query(Feed).all()

        # 计算未读数量
        unread_counts = {
            feed.id: self.session.query(Article)
            .filter(Article.feed_id == feed.id,
                    Article.read == False)
            .count()
            for feed in feeds
        }

        self._unread_counts = unread_counts or {}

        # 创建根节点
        today_item = QTreeWidgetItem(self, ["今日文章"])
        today_item.setData(0, Qt.UserRole, {"type": "today"})
        today_item.setIcon(0, QIcon.fromTheme('view-calendar-day'))

        unread_item = QTreeWidgetItem(self, ["未读文章"])
        unread_item.setData(0, Qt.UserRole, {"type": "unread"})
        unread_item.setIcon(0, QIcon.fromTheme('mail-mark-unread'))

        starred_item = QTreeWidgetItem(self, ["收藏文章"])
        starred_item.setData(0, Qt.UserRole, {"type": "starred"})
        starred_item.setIcon(0, QIcon.fromTheme('starred'))

        # 按分类组织
        categories = {}
        uncategorized = []

        for feed in feeds:
            if feed.category and feed.category.strip():
                categories.setdefault(feed.category, []).append(feed)
            else:
                uncategorized.append(feed)

        # 添加分类节点
        for category_name, feeds_in_category in categories.items():
            category_item = QTreeWidgetItem(self, [category_name])
            category_item.setData(0, Qt.UserRole, {"type": "category"})
            category_item.setIcon(0, QIcon.fromTheme('folder'))

            for feed in feeds_in_category:
                feed_item = QTreeWidgetItem(category_item, [
                    self._format_feed_title(feed)
                ])
                feed_item.setData(0, Qt.UserRole, {
                    "type": "feed",
                    "id": feed.id
                })
                feed_item.setIcon(0, QIcon.fromTheme('application-rss+xml'))

        # 添加未分类节点
        if uncategorized:
            uncat_item = QTreeWidgetItem(self, ["未分类"])
            uncat_item.setData(0, Qt.UserRole, {"type": "category"})
            uncat_item.setIcon(0, QIcon.fromTheme('folder-new'))

            for feed in uncategorized:
                feed_item = QTreeWidgetItem(uncat_item, [
                    self._format_feed_title(feed)
                ])
                feed_item.setData(0, Qt.UserRole, {
                    "type": "feed",
                    "id": feed.id
                })
                feed_item.setIcon(0, QIcon.fromTheme('application-rss+xml'))

        self.expandAll()  # 默认展开所有

    def _format_feed_title(self, feed):
        """格式化显示标题（含未读计数）"""
        count = self._unread_counts.get(feed.id, 0)
        return f"{feed.title} ({count})" if count > 0 else feed.title

    # def _on_item_clicked(self, item):
    #     """处理点击事件"""
    #     data = item.data(0, Qt.UserRole)
    #     if data:
    #         self.feed_selected.emit(data.get('id'), data.get('type'))

    def get_selected_feed_id(self):
        """获取当前选中的feed ID"""
        selected_items = self.selectedItems()
        if not selected_items:
            return None

        item = selected_items[0]
        data = item.data(0, Qt.UserRole)
        return data.get('id') if data and data.get('type') == 'feed' else None

    def get_selected_type(self):
        """获取选中项类型"""
        selected_items = self.selectedItems()
        if not selected_items:
            return None

        item = selected_items[0]
        data = item.data(0, Qt.UserRole)
        return data.get('type') if data else None

    def save_expanded_state(self):
        """保存展开状态"""
        self._expanded_state = {}
        iterator = QTreeWidgetItemIterator(self)
        while iterator.value():
            item = iterator.value()
            if item.childCount() > 0:  # 是有子项的节点
                self._expanded_state[item.text(0)] = item.isExpanded()
            iterator += 1

    def restore_expanded_state(self):
        """恢复展开状态"""
        if hasattr(self, '_expanded_state'):
            iterator = QTreeWidgetItemIterator(self)
            while iterator.value():
                item = iterator.value()
                if item.text(0) in self._expanded_state:
                    item.setExpanded(self._expanded_state[item.text(0)])
                iterator += 1


class ArticleTable(QTableWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.session = self.parent.session
        self.dbm = parent.dbm
        self.mark_read_timer = QTimer()
        self.mark_read_timer.setSingleShot(True)
        self.mark_read_timer.timeout.connect(self._mark_current_read)
        self.current_article_row = -1
        self.setup_ui()
        # 设置表格右键菜单
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)

    def setup_ui(self):
        """ 设置表格属性
        :return: None
        """

        self.setColumnCount(2)
        self.setHorizontalHeaderLabels(["标题", "发布时间"])

        # 设置表格属性
        self.setSelectionBehavior(QTableWidget.SelectRows)
        self.setSelectionMode(QTableWidget.SingleSelection)
        self.setEditTriggers(QTableWidget.NoEditTriggers)
        self.verticalHeader().setVisible(False)
        self.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeToContents)
        self.horizontalHeader().setSortIndicatorShown(True)
        # 默认按时间降序排序
        self.sortByColumn(1, Qt.DescendingOrder)
        self.horizontalHeader().sortIndicatorChanged.connect(self.sort_articles)


    def _mark_current_read(self):
        """标记当前选中文章为已读"""
        logger.debug(f"mark current read,current row:{self.current_article_row}")
        if self.current_article_row >= 0:
            article = self.get_article(self.current_article_row)
            if article and not article.read:
                # 更新数据库
                self.dbm.mark_read(article.id)
                # 更新UI
                logger.debug("update font")
                item = self.item(self.current_article_row, 0)
                font = item.font()
                font.setBold(False)
                item.setFont(font)

                self.parent.feed_tree.load_feeds()
                # self._update_row_appearance(self.current_article_row)

    def mousePressEvent(self, event):
        """点击文章时启动定时器"""
        super().mousePressEvent(event)
        row = self.rowAt(event.pos().y())
        if row >= 0:
            self.current_article_row = row
            delay = self.parent.settings.get_value("mark_read_delay") * 1000
            self.mark_read_timer.start(delay)

    def update_articles(self):
        """更新文章列表"""
        articles = self.parent.articles
        self.clear()
        self.setup_ui()
        self.setRowCount(len(articles))
        # 填充表格数据
        for row, article in enumerate(articles):
            # 标题列
            title_item = QTableWidgetItem(article.title)
            if article.starred:
                title_item.setIcon(QIcon.fromTheme('starred'))
            else:
                title_item.setIcon(self.parent.icon_manager.get_icon(article.feed))
            title_item.setData(Qt.UserRole, article)  # 存储完整文章对象
            if not article.read:
                font = title_item.font()
                font.setBold(True)
                title_item.setFont(font)

            # 时间列
            time_str = article.published.strftime('%Y-%m-%d %H:%M') if article.published else "未知时间"
            time_item = QTableWidgetItem(time_str)
            time_item.setData(Qt.UserRole, article)

            self.setItem(row, 0, title_item)
            self.setItem(row, 1, time_item)


        # 如果有文章，默认选中第一行
        if articles:
            self.setCurrentCell(0, 0)
            self.parent.update_article_content( articles[0] )
        logger.info(f"已加载 {len(articles)} 篇文章")

    def show_context_menu(self, pos):
        """

        :param pos:
        """
        menu = QMenu()
        row = self.rowAt(pos.y())

        if row >= 0:
            article = self.get_article(row)
            if article.starred:
                action = menu.addAction("取消收藏")
            else:
                action = menu.addAction("收藏文章")
            action.triggered.connect(lambda: self.toggle_starred(row))

            if article.read:
                action = menu.addAction("标记未读")
            else:
                action = menu.addAction("标记已读")
            action.triggered.connect(lambda: self.toggle_read(row))

            action = menu.addAction("标记所有文章为已读")
            action.triggered.connect(self.mark_read_all)

            menu.exec_(self.viewport().mapToGlobal(pos))

    def get_article(self, row):
        """
        get article of table row
        :param row: the row of table
        :return: None or article obj
        """
        item = self.item(row, 0)
        if item:
            return item.data(Qt.UserRole)
        else:
            return None

    def toggle_starred(self, row):
        """
        toggle article starred status
        :param row: row of article
        :return: None
        """
        article = self.get_article(row)
        if article:
            self.dbm.toggle_starred(article.id)
            self.update_articles()
            self.setCurrentCell(row, 0)
            self.parent.feed_tree.load_feeds()


    def toggle_read(self, row):
        """
        toggle article read status
        :param row: row of article
        :return:
        """
        article = self.get_article(row)
        if article:
            self.dbm.toggle_read(article.id)
            self.update_articles()
            self.setCurrentCell(row, 0)
            self.parent.feed_tree.load_feeds()

    def mark_read_all(self):
        """
        mark all articles in table read
        :return:
        """
        articles = self.parent.articles
        self.dbm.mark_read_articles(articles)
        self.update_articles()
        self.parent.feed_tree.load_feeds()

    def sort_articles(self, column, order):
        """处理排序"""
        self.sortItems(column, order)